package vg.modules.backlight;

import java.util.Collection;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import org.apache.commons.lang.mutable.MutableBoolean;
import vg.modules.backlight.components.CriticalPathSearcher;
import vg.modules.backlight.components.CycleSearcher;
import vg.modules.backlight.components.PathsSearcher;
import vg.services.data_base_manager.data.graph.Attribute;
import vg.services.data_base_manager.data.graph.Edge;
import vg.services.data_base_manager.data.graph.Graph;
import vg.services.data_base_manager.data.graph.Vertex;
import vg.services.graph_view_manager.interfaces.graph_view.AGraphView;
import vg.services.graph_view_manager.interfaces.graph_view.GraphObserverAdapter;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphObserver;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphRenderer;
import vg.services.graph_view_manager.interfaces.tab.ATab;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.actions.DefaultActionAdapter;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.actions.GraphObserverAction;
import vg.services.plugin_manager.event_and_request.event.AUIEvent;
import vg.services.plugin_manager.event_and_request.event.UIEventChangeTab;
import vg.services.plugin_manager.interfaces.IPlugin;
import vg.services.plugin_manager.realization.PluginParameter;
import vg.services.user_interface_manager.interfaces.IUserInterfaceManager;
import vg.services.user_interface_manager.interfaces.AUserInterfaceElement;
import vg.services.user_interface_manager.interfaces.UserInterfaceObserverAdapter;

public class PathSelectingPlugin implements IPlugin {
	@Override
	public void install(final PluginParameter pluginParameter) throws Exception {
        new PathSelectingPanel(pluginParameter.userInterfaceManager);
	}

	private static class PathSelectingPanel extends AUserInterfaceElement {
		private CycleSearcher cycleSearcher;
		private PathsSearcher pathsSearcher;
		private CriticalPathSearcher criticalPathSearcher;
		private JToolBar toolBar;
		private IGraphObserver observer;
		private AGraphView view;
		
		public PathSelectingPanel(IUserInterfaceManager userInterfaceManager) {
			super("PathSelectingPlugin", null);
			this.observer = new GraphObserverAdapter() {
                @Override
                public void updateSelectedElements(Map<Vertex, Map<Attribute, MutableBoolean>> selectedVertex, Map<Edge, Map<Attribute, MutableBoolean>> selectedEdge) {
                    checkView();
                }
			};

			this.pathsSearcher = new PathsSearcher();
			this.criticalPathSearcher = new CriticalPathSearcher();
			this.cycleSearcher = new CycleSearcher();
			
			toolBar = new JToolBar();
			toolBar.setFloatable(false);
			toolBar.add(cycleSearcher.getView());
			toolBar.add(pathsSearcher.getView());
			toolBar.add(criticalPathSearcher.getView());
            userInterfaceManager.addInstrument(this);

            userInterfaceManager.addObserver(new UserInterfaceObserverAdapter() {
                @Override
                public void dispatchEvent(AUIEvent event) {
                    switch (event.getType()) {
                        case DEF_CHANGE_UI_STYLE: {
                            SwingUtilities.updateComponentTreeUI(toolBar);
                            break;
                        }
                        case DEF_CHANGE_TAB: {
                            if (view != null) {
                                view.addAction(new GraphObserverAction(GraphObserverAction.REMOVE_SELECT_OBSERVER_ACTION, observer));
                            }
                            UIEventChangeTab bufEvent = (UIEventChangeTab) event;
                            ATab tab = bufEvent.getTab();
                            if (tab != null) {
                                switch (tab.getTabType()) {
                                    case ATab.DEF_GRAPH_VIEW_TAB_TYPE: {
                                        view = (AGraphView)tab;
                                        view.addAction(new GraphObserverAction(GraphObserverAction.ADD_SELECT_OBSERVER_ACTION, observer));
                                        cycleSearcher.changeView(view);
                                        criticalPathSearcher.changeView(view);
                                        pathsSearcher.changeView(view);
                                        checkView();
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                        default:break;
                    }
                }
            });
		}

		@Override
		public JComponent getView() {
			return toolBar;
		}

		/**
		 * This method checks view on conditional (selection subgraph must contain one vertex).
		 */
		private void checkView() {
			if (!SwingUtilities.isEventDispatchThread()) {
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						checkView();
					}
				});
				return;
			}

			if (view != null) {
                view.addAction(new DefaultActionAdapter("cycle searching action") {
                    @Override
                    public void action(final IGraphRenderer graphRenderer) {
                        Graph graph = graphRenderer.getOriginalSelectedSubGraph();
                        if (graph != null) {
                            Collection<Vertex> lv = graph.getVertices();
                            if (lv != null) {
                                boolean cycleCheck = (lv.size() == 1);
                                boolean pathCheck = (lv.size() == 2);

                                cycleSearcher.setEnabled(cycleCheck);
                                criticalPathSearcher.setEnabled(pathCheck);
                                pathsSearcher.setEnabled(pathCheck);
                            }
                        }
                    }
                });
            }
		}
	}
}
